﻿using System;
using System.Collections.Generic;
using System.Text;
using XLETL.Common;
using XLETL.Model;
using System.Linq;
using System.Xml.Linq;
using System.IO;

namespace XLETL.BLL
{
  /// <summary>
  /// Business Component to manage Admin
  /// </summary>
  public class Admin
  {
    /// <summary>
    /// Save Admin Credentials into the system
    /// </summary>
    public bool SaveAdminCredentials(AdminInfo admin)
    {
      if (admin == null)
      {
        throw new ArgumentNullException("Parameter \"admin\" is null");
      }

      XElement admins = new XElement(AdminInfo.ADMIN_COL);

      if (File.Exists(GlobalCache.ADMIN_STORAGE_PATH))
      {
        // load all admins
        XElement existingAdmins = XElement.Load(GlobalCache.ADMIN_STORAGE_PATH);

        IEnumerable<XElement> singleAdmin = null;
        Guid adminID;

        // only update 
        if (!admin.Id.Equals(Guid.Empty))
        {
          adminID = admin.Id;

          //obtain a single admin
          singleAdmin = (from targetAdmin in existingAdmins.Elements(AdminInfo.ADMIN_INFO)
                         where ((Guid)targetAdmin.Element(AdminInfo.ADMIN_ID)).Equals(adminID)
                         select targetAdmin);
        }
        else
        {
          adminID = Guid.NewGuid();
        }

        XElement newAdmin = new XElement(AdminInfo.ADMIN_INFO,
   new XElement(AdminInfo.ADMIN_ID, adminID),
   new XElement(AdminInfo.USERNAME, admin.UserName),
   new XElement(AdminInfo.PASSWORD, admin.Password)   
   );

        if (singleAdmin != null)
        {
          //update admin, should only be 1
          foreach (XElement xe in singleAdmin)
          {
            //xe.Remove();
            xe.ReplaceWith(newAdmin);
          }

          existingAdmins.Save(GlobalCache.ADMIN_STORAGE_PATH);

        }
        else
        {
          admins.Add(existingAdmins.Elements(AdminInfo.ADMIN_INFO));
          admins.Add(newAdmin);
          admins.Save(GlobalCache.ADMIN_STORAGE_PATH);
        }

        return true;
      }
      else
      {
        return false;
      }
    }

    /// <summary>
    /// Verify admin credentials by username, password
    /// </summary>
    public bool VerifyAdminCredentials(AdminInfo adminInfo)
    {
      if (File.Exists(GlobalCache.ADMIN_STORAGE_PATH))
      {
        XElement existingAdmins = XElement.Load(GlobalCache.ADMIN_STORAGE_PATH);

        //obtain a single admin
        IEnumerable<XElement> singleAdmin = (from targetAdmin in existingAdmins.Elements(AdminInfo.ADMIN_INFO)
                                             where ((string)targetAdmin.Element(AdminInfo.USERNAME)).Equals(adminInfo.UserName) &&
                       ((string)targetAdmin.Element(AdminInfo.PASSWORD)).Equals(adminInfo.Password)
                       select targetAdmin);
        /*
        var admins = from adminElement in existingAdmins.Elements(AdminInfo.ADMIN_INFO)
                     let uname = (string)adminElement.Element(AdminInfo.USERNAME)
                     let upass = (string)adminElement.Element(AdminInfo.PASSWORD)
                     where uname.Equals(username) && upass.Equals(password)
                    select new AdminInfo
                    {
                      Id = (Guid)adminElement.Element(AdminInfo.ADMIN_ID),
                      UserName = (string)adminElement.Element(AdminInfo.USERNAME),
                      Password = (string)adminElement.Element(AdminInfo.PASSWORD)
                    };*/
        return (singleAdmin.Count<XElement>() > 0);
      }
      else return false;
    }

    public List<AdminInfo> GetAdminRecords()
    {
      if (File.Exists(GlobalCache.ADMIN_STORAGE_PATH))
      {
        XElement existingAdmins = XElement.Load(GlobalCache.ADMIN_STORAGE_PATH);

        var admins = from adminElement in existingAdmins.Elements(AdminInfo.ADMIN_INFO)
                     select new AdminInfo
                    {
                      Id = (Guid)adminElement.Element(AdminInfo.ADMIN_ID),
                      UserName = (string)adminElement.Element(AdminInfo.USERNAME),
                      Password = (string)adminElement.Element(AdminInfo.PASSWORD)
                    };
        return admins.ToList<AdminInfo>();
      }
      else return new List<AdminInfo>();
    }

    /// <summary>
    /// Method to count the number of existing admin records
    /// </summary>
    /// <returns></returns>
    public int CountAdminRecords()
    {
      if (File.Exists(GlobalCache.ADMIN_STORAGE_PATH))
      {
        XElement existingAdmins = XElement.Load(GlobalCache.ADMIN_STORAGE_PATH);

        //obtain all records
        IEnumerable<XElement> admins = (from targetAdmin in existingAdmins.Elements(AdminInfo.ADMIN_INFO) select targetAdmin);
        return admins.Count<XElement>();
      }
      else return 0;
    }
  }
}
